﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Domain.MainModule.Entities;
using Infraestructure.Data.MainModule.UnitOfWork;
using Infraestructure.CrossCutting.Logging;
using Domain.MainModule.Employees;
using Infraestructure.Data.MainModule.Repositories;

namespace Infraestructure.Data.MainModule.Tests.RepositoriesTests
{
    [TestClass()]
    public class EmployeeRepositoryTest : CustomRepositoryTestsBase<Employee, User>
    {

        public override System.Linq.Expressions.Expression<Func<Employee, bool>> FilterExpression
        {
            get { return a => a.LastName == "Lazarte"; }
        }

        public override System.Linq.Expressions.Expression<Func<Employee, Guid>> OrderByExpression
        {
            get { return a => a.UserId; }
        }

        [TestMethod()]
        public void AddEmployee_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            Employee employee = new Employee()
            {
                FirstName = "Sebastian",
                FirstSurname = "Lazarte",
                FullName = "Sebastian Lazarte",
                GenderId = TestConstants.Instance.GENDER_ID,
                IsEnabled = true,
                LastName = "Lazarte",
                LastSurname = "Chauque",
                MaritalStatusId = TestConstants.Instance.MARITAL_STATUS_ID,
                IsLocked = false,
                MembershipUserId = TestConstants.Instance.MEMBERSHIP_USER_ID,
                NacionalityCountryId = TestConstants.Instance.COUNTRY_ID,
                PinNumber = "123455",
            };
                

            //Act
            repository.Add(employee);
            //Assert
            Assert.IsNotNull(employee.UserId);
        }


        [TestMethod()]
        [ExpectedException(typeof(ArgumentNullException))]
        public void FindEmployee_Invoke_NullSpecThrowNewArgumentNullException_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            //Act
            repository.FindEmployee(null);
        }

        #region EmployeeUserIdSpecification

        [TestMethod()]
        public void FindEmployee_Invoke_InvalidUserIdReturnNullObject_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            Guid invalidId = new Guid("11111111-1111-1111-1111-111111111111");
            EmployeeUserIdSpecification spec = new EmployeeUserIdSpecification(invalidId);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNull(employee);
        }

        [TestMethod()]
        public void FindEmployeeByUserId_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            EmployeeUserIdSpecification spec = new EmployeeUserIdSpecification(TestConstants.Instance.EMPLOYEE_ID);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNotNull(employee);
        }

        [TestMethod()]
        public void FindEmployeeBySpecificationUserId_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            EmployeeUserIdSpecification spec = new EmployeeUserIdSpecification(TestConstants.Instance.EMPLOYEE_ID);

            //Act
            IEnumerable<Employee> employees = repository.GetBySpec(spec);

            //Assert
            Assert.IsNotNull(employees);
        }

        [TestMethod()]
        public void FindEmployeePaged_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            EmployeeUserIdSpecification spec = new EmployeeUserIdSpecification(TestConstants.Instance.EMPLOYEE_ID);

            //Act
            IEnumerable<Employee> employees = repository.GetPagedElements<Employee>(1, 10, spec);

            //Assert
            Assert.IsNotNull(employees);
        }

        #endregion

        #region EmployeeBranchSpecification

        [TestMethod()]
        public void FindEmployee_Invoke_InvalidBranchIdReturnNullObject_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            Guid invalidId = new Guid("11111111-1111-1111-1111-111111111111");
            EmployeeBranchSpecification spec = new EmployeeBranchSpecification(invalidId);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNull(employee);
        }

        [TestMethod()]
        public void FindEmployeeByBranchId_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            EmployeeBranchSpecification spec = new EmployeeBranchSpecification(TestConstants.Instance.BRANCH_ID);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNotNull(employee);
        }

        #endregion

        #region EmployeeMembershipUserIdSpecification

        [TestMethod()]
        public void FindEmployee_Invoke_InvalidMembershipUserIdReturnNullObject_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            Guid invalidId = new Guid("11111111-1111-1111-1111-111111111111");
            EmployeeMembershipUserIdSpecification spec = new EmployeeMembershipUserIdSpecification(invalidId);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNull(employee);
        }

        [TestMethod()]
        public void FindEmployeeByMembershipUserId_Invoke_Test()
        {
            //Arrange 
            IMainModuleUnitOfWork context = GetUnitOfWork();
            ITraceManager traceManager = this.GetTraceManager();
            IEmployeeRepository repository = new EmployeeRepository(context, traceManager);

            EmployeeMembershipUserIdSpecification spec = new EmployeeMembershipUserIdSpecification(TestConstants.Instance.MEMBERSHIP_USER_ID);

            //Act
            Employee employee = repository.FindEmployee(spec);

            //Assert
            Assert.IsNotNull(employee);
        }

        #endregion
    }
}
